package com.jessechanrui.template.common.template.auth.config.interceptor;

import com.jessechanrui.template.common.template.auth.application.dto.UserDTO;
import com.jessechanrui.template.common.template.auth.application.service.LoginService;
import com.jessechanrui.template.common.template.auth.common.AuthorizationSupport;
import com.jessechanrui.template.common.template.auth.common.Ignore;
import com.jessechanrui.template.common.template.auth.config.AuthConfigProperties;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import java.lang.reflect.Method;

/**
 * @author chenrui
 * @version 1.0
 * @description AuthInterceptor
 * @date 2025/4/30
 */
@Component
public class AuthInterceptor implements HandlerInterceptor, ApplicationContextAware {

    @Autowired
    AuthConfigProperties authConfigProperties;

    private ApplicationContext applicationContext;

    private LoginService loginService;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    private LoginService getLoginService() {
        if (loginService == null) {
            loginService = applicationContext.getBean(LoginService.class);
        }
        return loginService;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        Method method = null;
        if (!authConfigProperties.getEnable()) {
            return true;
        }
        if (handler instanceof HandlerMethod) {
            method = ((HandlerMethod) handler).getMethod();
        }
        // 检查是否忽略权限验证
        if (method == null || checkIgnore(method)) {
            return true;
        }
        // 获取token
        String token = AuthorizationSupport.getTokenFromRequest(request);

        if (StringUtils.isEmpty(token)) {
            throw new RuntimeException("缺少验证token");
        } else {
            // 保存到ThreadLocal中
            loginService = getLoginService();
            UserDTO current = loginService.current(token);
            AuthorizationSupport.setUser(token, current);
        }
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
        AuthorizationSupport.removeUser();
    }

    private boolean checkIgnore(Method method) {
        Ignore annotation = method.getAnnotation(Ignore.class);
        if (annotation == null) {
            annotation = method.getDeclaringClass().getAnnotation(Ignore.class);
            return annotation != null;
        }
        return true;
    }
}
